home *** CD-ROM | disk | FTP | other *** search
- /*
- File: Exceptions.h
-
- Contains: exception handling macros
-
- Written by: Bruce Horn, Steve Capps, Larry Kenyon, John Meier, scott douglass, Darin Adler,
- Paul Mercer, Bryan Stearns, Dave Owens
-
- Andy Nicholas
-
- Copyright: © 1988-1995 by Apple Computer, Inc., all rights reserved.
-
- <2> 2/24/95 ga
- */
-
- #ifndef Exceptions_h
- #define Exceptions_h
-
- typedef SInt32 ExceptionCode;
-
- #define gExceptionStack __except_buffer
- #define Throw(err) throw (ExceptionCode)(err)
- #define Try try
- #define Catch(err) catch(ExceptionCode err)
-
-
- #define eUnimplemented -29999
- #define eWrongDataType -30000
- #define eRequireFailed -30001
- #define eIndexOutOfRange -30002
- #define eDataCorrupt -30003
- #define eLinksCorrupt -30004
- #define eNilPtr 'nilP'
-
- #define Require(x) if(x == false) Throw(eRequireFailed);
-
- #define FailNil(x) if(x == nil) Throw(eNilPtr)
-
- #define NOREGISTER(x) (&x)
-
- //----------------------------------------------------------------------------------------
- // FailErr:
- //----------------------------------------------------------------------------------------
- inline void FailErr(ExceptionCode error)
- {
- if (error != 0)
- Throw(error);
- }
-
- class TException;
-
- extern TException* gExceptionStack;
-
- #if 0
-
- #include <Types.h>
- #include <setjmp.h>
-
- #ifdef METROWERKSPOWERPC
- struct DestructorChain; // Forward declaration of Metrowerks local destructor chain type
- #endif
-
- extern SInt32 gExceptionMessage;
- extern SInt32 gExceptionError;
-
- void Fail(SInt32, SInt32 message);
- void FailErr(SInt32);
- void FailAgain();
- void FailNil(void*);
-
- const long nilPtrErr = -110; // Same as memAdrErr--odd or out of range
- const OSErr ePointerNil = -110;
- const OSErr eGeneralErr = -1;
- const OSErr eAssertionFailure = -30000;
- const OSErr eRequirementNotMet = -30001;
- const OSErr eValueOutOfRange = -30002;
- const OSErr eIndexOutOfRange = -30003;
- const OSErr eLinksCorrupt = -30004;
- const OSErr eDataCorrupt = -30005;
- const OSErr eWrongDataType = -30006;
- const OSErr eFunctionNotHandledByClass = -30007;
-
- //----------------------------------------------------------------------------------------
- // Except_Error:
- //----------------------------------------------------------------------------------------
- inline SInt32 Except_Error()
- {
- return gExceptionError;
- }
-
- //----------------------------------------------------------------------------------------
- // Except_Message:
- //----------------------------------------------------------------------------------------
- inline SInt32 Except_Message()
- {
- return gExceptionMessage;
- }
-
- //----------------------------------------------------------------------------------------
- // ExpectError:
- //----------------------------------------------------------------------------------------
- inline void ExpectError(OSErr error)
- {
- if (Except_Error() != error) FailAgain();
- }
-
- //----------------------------------------------------------------------------------------
- // FailErr:
- //----------------------------------------------------------------------------------------
- inline void FailErr(SInt32 error)
- {
- if (error != noErr)
- Fail(error, 0);
- }
-
- //----------------------------------------------------------------------------------------
- // FailNil:
- //----------------------------------------------------------------------------------------
- inline void FailNil(void *pointer)
- {
- if (pointer == nil)
- FailErr(nilPtrErr);
- }
-
- //========================================================================================
- // CLASS TExceptionAction
- //
- // Exception action objects may be attached to the current exception handler; if
- // an exception is thrown, then the virtual method 'CatchException' is called, and
- // the exception-action object may do whatever cleanup it needs to.
- //========================================================================================
-
- class TExceptionAction
- {
- public:
- virtual void CatchException() = 0;
-
- TExceptionAction* GetNextExceptionAction() { return fNextAction; }
- void SetNextExceptionAction(TExceptionAction* nextAction) { fNextAction = nextAction; }
-
- private:
- TExceptionAction* fNextAction;
- };
-
-
- //========================================================================================
- // CLASS TException
- //========================================================================================
-
- class TException
- {
- public:
-
- //
- // --- Methods -------------------------------------------------------------------------------------
- //
- TException(); // to set up next & fired
- ~TException(); // to remove from the exceptions stack
-
- void AddExceptionAction(TExceptionAction* exceptAction); // Add an exception action object to the the exception frame
- TExceptionAction* RemoveExceptionAction(TExceptionAction* exceptAction = nil); // Remove a loop from the exception frame
-
- //
- // --- Fields --------------------------------------------------------------------------------------
- //
- jmp_buf fEnv; // jmp_buf has to be first
-
- #ifdef SIXTYEIGHTK
- SInt32 fA5; // Save the current A5
- #endif
-
- #ifdef METROWERKSPOWERPC
- DestructorChain* fLocalDestructorChain; // • temporary Metrowerks hack
- #endif
-
- TExceptionAction* fExceptionAction; // A pointer to the first exception action object
- TException* fPrevious; // A pointer to the previous exception frame on the stack
-
- Boolean fFired;
- };
-
-
- //----------------------------------------------------------------------------------------
- // TException::AddExceptionAction:
- //
- // Insert 'exceptAction' into the linked-list of exception-actions hanging off the
- // exception frame
- //----------------------------------------------------------------------------------------
- inline void TException::AddExceptionAction(TExceptionAction* exceptAction)
- {
- exceptAction->SetNextExceptionAction(fExceptionAction);
- fExceptionAction = exceptAction;
- }
-
- //----------------------------------------------------------------------------------------
- // TException::RemoveExceptionAction:
- //
- // Remove a single loop from the linked-list of loops hanging off the exception frame
- //----------------------------------------------------------------------------------------
- inline TExceptionAction* TException::RemoveExceptionAction(TExceptionAction* exceptAction /* = nil */)
- {
- if((exceptAction == fExceptionAction) || (exceptAction == nil))
- {
- exceptAction = fExceptionAction;
- fExceptionAction = fExceptionAction->GetNextExceptionAction();
- }
- else
- {
- TExceptionAction* actionList;
-
- while(actionList != nil)
- {
- TExceptionAction* nextAction = actionList->GetNextExceptionAction();
- if(nextAction == exceptAction)
- {
- actionList->SetNextExceptionAction(nextAction->GetNextExceptionAction());
- actionList = nil;
- }
- else
- actionList = nextAction;
- }
- }
-
- return exceptAction;
- }
-
-
- //
- // TRY/EXCEPT/ENDTRY Usage:
- //
- // Advantage: Every failure handler has its own scope
- // Disadvantage: Requires ugly "ENDTRY", and forgetting it
- // causes strange errors much later in the file
- //
- // TRY
- // {
- // // do something
- // FailErr(SomeFnReturningOSErr());
- // }
- // EXCEPT
- // {
- // OSErr err = Except_Error();
- //
- // // clean up
- // FailAgain();
- // }
- // ENDTRY
- //
- #define TRY { TException exceptions_data; \
- if (setjmp(exceptions_data.fEnv) == 0) {
- #define EXCEPT } else {
- #define ENDTRY } }
- #define NOREGISTER(x) ((void)&x)
-
- //
- // Try/Catch/Throw Usage:
- //
- // Advantage: No ugly "ENDTRY"; looks very similar to C++ try/catch
- // Disadvantage: Must wrap each failure handler in its own scope,
- // or you will get an error "fi defined twice"
- //
- // OSErr err = noErr;
- //
- // Try
- // {
- // // do something
- // FailErr(SomeFnReturningOSErr()); // "Throw" is unconditional
- // }
- // Catch(err)
- // {
- // // clean up
- // Throw(err);
- // }
- //
- #define Try TException fi; if(setjmp(fi.fEnv) == 0) for(; gExceptionStack == &fi; gExceptionStack = fi.fPrevious, fi.fFired = true)
- #define Catch(err) else if((err = (OSErr) Except_Error()) != noErr)
- #define Throw(err) Fail(err, 0)
- #define Require(b) if(b == false) Throw(-1)
-
- //
- // try/catch/throw usage:
- //
- // Advantage: Supported by the compiler, so it's portable
- // Disadvantage: Most of our compilers don't provide exception handling
- //
- // try
- // {
- // // do something
- // FailErr(SomeFnReturningOSErr()); // "throw" is unconditional, so we still need a FailErr
- // }
- // catch(OSErr err)
- // {
- // // clean up
- // throw(err);
- // }
- //
-
- //
- // How to combine Try/Catch with try/catch to form an
- // exception mechanism that works on compilers that
- // do support exception handling, and also build on
- // compilers that do not support it:
- //
- // Define a type "ExceptionOSErr", which is just an
- // OSErr. If exceptions are supported, ExceptionOSErr
- // is #defined to be OSErr. If it is not supported,
- // then it is #defined to be nothing.
- //
- // The catch is that you must always use the type
- // ExceptionOSErr in your catch blocks, you must
- // always throw OSErrs, and the variable in the
- // catch block must always be exceptionErr.
- //
- // try
- // {
- // // do something
- // FailErr(SomeFnReturningOSErr()); // "throw" is unconditional, so we still need a FailErr
- // }
- // catch(ExceptionOSErr exceptionErr)
- // {
- // // clean up
- // throw(err);
- // }
- //
- // The problem is that our exception handler saves extra state
- // (TopMapHandle, CurMap, CurApRefNum, and Zone) that will NOT
- // be saved by a compiler-supported exception handler.
- //
- // I need to look into ways of patching into the 'try/catch'
- // process...
- // - ga
- //
- // EXCEPTIONSSUPPORTED
- //
-
- #ifdef FUTURECODE // Don't use this yet...
-
- // EXCEPTIONSSUPPORTED
-
- #define ExceptionOSErr OSErr
-
- // !EXCEPTIONSSUPPORTED
-
- #define ExceptionOSErr OSErr
-
- #define try OSErr exceptionErr; TException fi; if(setjmp(fi.fEnv) == 0) while(fi.fFired == false)
- #define catch else if((err = Except_Error()) != noErr)
- #define throw(err) Fail(err, 0)
-
- #endif // Don't use this yet
-
- #endif
-
- #endif
-
-